﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Reflection;

public class QIsNullParam
{
    public IQEvaluable Column { get; set; }
    public Object Constant { get; set; }
    public QIsNullParam() { }
    public QIsNullParam(IQEvaluable column, Object constant)
    {
        this.Column = column; this.Constant = constant;
    }
}

public class QIsNull : QIsNullParam, IQEvaluable
{
    public QIsNull(string column, Object constant)
        : this(column: new QColumn(column), constant: new QColumn(column))
    {
    }
    public QIsNull(IQEvaluable column, Object constant)
    {
        this.Column = column;
        this.Constant = constant;
    }

    public string Evalute()
    {
        return string.Format("IsNull({0},{1})", this.Column.Evalute(), QueryUtil.FormatValue(this.Constant));
    }

    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}

public class QMax : IQEvaluable
{
    public IQEvaluable Column { get; set; }

    public QMax(string column)
    {
        this.Column = new QColumn(column);
    }

    public QMax(IQEvaluable column)
    {
        this.Column = column;
    }

    public string Evalute()
    {
        return string.Format("max({0})", this.Column.Evalute());
    }


    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}
public class QCount : IQEvaluable
{
    public string Column { get; set; }

    public QCount(string column)
    {
        this.Column = column;
    }

    public string Evalute()
    {
        return string.Format("Count({0})", this.Column);
    }

    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}
public class QMin : IQEvaluable
{
    public IQEvaluable Column { get; set; }

    public QMin(string column)
    {
        this.Column = new QColumn(column);
    }

    public QMin(IQEvaluable column)
    {
        this.Column = column;
    }

    public string Evalute()
    {
        return string.Format("max({0})", this.Column.Evalute());
    }


    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}

public class QAvg : IQEvaluable
{
    public IQEvaluable Column { get; set; }

    public QAvg(string column)
    {
        this.Column = new QColumn(column);
    }

    public QAvg(IQEvaluable column)
    {
        this.Column = column;
    }

    public string Evalute()
    {
        return string.Format("max({0})", this.Column.Evalute());
    }




    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}
public class QAbs : IQEvaluable
{
    public IQEvaluable Column { get; set; }

    public QAbs(string column)
    {
        this.Column = new QColumn(column);
    }

    public QAbs(IQEvaluable column)
    {
        this.Column = column;
    }

    public string Evalute()
    {
        return string.Format("abs({0})", this.Column.Evalute());
    }

    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}
public class QSum : IQEvaluable
{
    public IQEvaluable Column { get; set; }

    public QSum(string column)
    {
        this.Column = new QColumn(column);
    }

    public QSum(IQEvaluable column)
    {
        this.Column = column;
    }

    public string Evalute()
    {
        return string.Format("sum({0})", this.Column.Evalute());
    }

    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}
public class QMonth : IQEvaluable
{
    public IQEvaluable Column { get; set; }

    public QMonth(string column)
    {
        this.Column = new QColumn(column);
    }

    public QMonth(IQEvaluable column)
    {
        this.Column = column;
    }

    public string Evalute()
    {
        return string.Format("month({0})", this.Column.Evalute());
    }
    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}
public class QYear : IQEvaluable
{
    public IQEvaluable Column { get; set; }

    public QYear(string column)
    {
        this.Column = new QColumn(column);
    }

    public QYear(IQEvaluable column)
    {
        this.Column = column;
    }

    public string Evalute()
    {
        return string.Format("year({0})", this.Column.Evalute());
    }
    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}
public class QDay : IQEvaluable
{
    public IQEvaluable Column { get; set; }

    public QDay(string column)
    {
        this.Column = new QColumn(column);
    }

    public QDay(IQEvaluable column)
    {
        this.Column = column;
    }

    public string Evalute()
    {
        return string.Format("day({0})", this.Column.Evalute());
    }
    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}
public class QReplace : IQEvaluable
{
    public IQEvaluable Text { get; set; }
    public IQEvaluable OldValue { get; set; }
    public IQEvaluable NewValue { get; set; }

    public QReplace(IQEvaluable test, IQEvaluable oldValue, IQEvaluable newValue)
    {
        this.Text = test;
        this.OldValue = oldValue;
        this.NewValue = newValue;
    }

    public QReplace(IQEvaluable test, string oldValue, string newValue)
    {
        this.Text = test;
        this.OldValue = new QConstant(oldValue);
        this.NewValue = new QConstant(newValue);
    }

    public string Evalute()
    {
        return string.Format("replace({0},{1},{2})", this.Text.Evalute(), this.OldValue.Evalute(), this.NewValue.Evalute());
    }

    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}

public class QCast : IQEvaluable
{
    public IQEvaluable Expression { get; set; }
    public IQEvaluable Type { get; set; }


    public QCast(IQEvaluable expression, IQEvaluable type)
    {
        this.Expression = expression;
        this.Type = type;

    }

    public string Evalute()
    {

        return string.Format("cast({0} as {1})", this.Expression.Evalute(), this.Type.Evalute());
    }



    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}


public class QNow : IQEvaluable
{
    public string Evalute()
    {
        return "GetDate()";
    }


    public string EvaluteWithAlias()
    {
        throw new NotImplementedException();
    }
}
//public class QCast : IFunction
//{
//    public string Column { get; set; }
//    public QCast(string column)
//    {
//        this.Column = column;
//    }

//    public string Evalute()
//    {
//        return string.Format("Count({0})", this.Column);
//    }
//}